using System;
using System.Text;
using System.Collections.Generic;
using NUnit.Framework;
using Microsoft.Practices.RepositoryFactory.CommonHelpers;
using Microsoft.Practices.RepositoryFactory.CodeGeneration.ObjectModel;
using System.Xml;
using Microsoft.Practices.RepositoryFactory.CodeGeneration.ObjectModel.Mappings;
using Microsoft.Practices.RepositoryFactory.SchemaDiscovery.ObjectModel.Base;
using System.Diagnostics;
using System.Collections;

namespace Microsoft.Practices.RepositoryFactory.Tests.CommonHelpers
{
    /// <summary>
    /// Summary description for EntitySerializerHelperFixture
    /// </summary>
    [TestFixture]
    public class EntitySerializerHelperFixture
    {
        [Test]
        [ExpectedException(typeof(ArgumentNullException))]
        public void EntityCannotBeNull()
        {
            EntitySerializerHelper serializer = new EntitySerializerHelper(new XmlDocument());
            serializer.PersistEntityMappings((Entity)null);
        }

        [Test]
        public void ShouldSerializeEntity()
        {
            Entity entity = new Entity();
            entity.Name = "Entity";

            EntitySerializerHelper serializer = new EntitySerializerHelper(new XmlDocument());
            XmlNode node = serializer.PersistEntityMappings(entity);

            Assert.IsNotNull(node);
            Assert.AreEqual(node.Name, "repositoryMetadata");
            Assert.IsNotNull(node.Attributes["name"]);
            Assert.AreEqual(node.Attributes["name"].Value, entity.Name);
        }

        [Test]
        public void ShouldSerializeSprocMappings()
        {
            Entity entity = new Entity();
            entity.Name = "Person";
            entity.StoredProcedureMappings = new List<Microsoft.Practices.RepositoryFactory.CodeGeneration.ObjectModel.Mappings.EntityStoredProcedureMapping>();
            EntityStoredProcedureMapping mapping = new EntityStoredProcedureMapping("PersonGetPerson", true, "Get", Microsoft.Practices.RepositoryFactory.CodeGeneration.ObjectModel.Mappings.Enums.OperationType.GetOne);
            entity.StoredProcedureMappings.Add(mapping);

            EntitySerializerHelper serializer = new EntitySerializerHelper(new XmlDocument());
            XmlNode node = serializer.PersistEntityMappings(entity);

            XmlNode sprocMappingNode = node.ChildNodes[0];
            Assert.IsNotNull(node.ChildNodes[0]);
            Assert.AreEqual(sprocMappingNode.Attributes["operationName"].Value, mapping.OperationName);
            Assert.AreEqual(sprocMappingNode.Attributes["hasInputParameters"].Value, mapping.ProcedureHasInputParameters.ToString());
            Assert.AreEqual(sprocMappingNode.Attributes["procedure"].Value, mapping.Procedure);
            Assert.AreEqual(sprocMappingNode.Attributes["operationType"].Value, mapping.OperationType.ToString());

        }

        [Test]
        public void ShouldSerializeSprocMappingsParameters()
        {
            Entity entity = new Entity();
            entity.Name = "Person";
            entity.StoredProcedureMappings = new List<Microsoft.Practices.RepositoryFactory.CodeGeneration.ObjectModel.Mappings.EntityStoredProcedureMapping>();
            EntityStoredProcedureMapping mapping = new EntityStoredProcedureMapping("PersonGetPerson", true, "Get", Microsoft.Practices.RepositoryFactory.CodeGeneration.ObjectModel.Mappings.Enums.OperationType.GetOne);
            
            Parameter dbParameter = new Parameter();
            dbParameter.DBName = "parameterName";

            mapping.ParameterMappings.Add(new PropertyParameterMapping("property", dbParameter));
            entity.StoredProcedureMappings.Add(mapping);
            PropertyParameterMapping parameter = mapping.ParameterMappings[0];

            EntitySerializerHelper serializer = new EntitySerializerHelper(new XmlDocument());
            XmlNode node = serializer.PersistEntityMappings(entity);

            XmlNode parameterMappingNode = node.ChildNodes[0].ChildNodes[0];
            XmlNode dbParameterNode = parameterMappingNode.ChildNodes[0];
            Assert.AreEqual(parameterMappingNode.Name, "parameter");
            Assert.AreEqual(parameterMappingNode.Attributes["propertyName"].Value, parameter.Property);
            Assert.AreEqual(parameterMappingNode.Attributes["parameterName"].Value, parameter.Parameter);
            
        }

        [Test]
        public void ShouldPersistsMultiplEntities()
        {
            Entity e1 = new Entity();
            e1.Name = "Person";
            Entity e2 = new Entity();
            e1.Name = "Person2";



            XmlDocument rcpStateDocument = new XmlDocument();
            EntitySerializerHelper serializer = new EntitySerializerHelper(rcpStateDocument);
            serializer.PersistEntityMappings(new ArrayList(new Entity[] { e1, e2 }));
            Assert.AreEqual(2, rcpStateDocument.ChildNodes[0].ChildNodes.Count);
        }

        [Test]
        public void ShouldReturnIfHasPreviousInformationForEntity()
        {
            string previousData = "<repositoryInformation><repositoryMetadata name=\"Person\"><operation operationName=\"DeletePerson\" hasInputParameters=\"True\" procedure=\"DeletePerson\" operationType=\"DeleteOne\" /></repositoryMetadata></repositoryInformation>";

            XmlDocument document = new XmlDocument();
            document.LoadXml(previousData);

            EntitySerializerHelper serializer = new EntitySerializerHelper(document);
            
            Entity entity = new Entity();
            entity.Name = "Person";
            Assert.IsTrue(serializer.HasStateInformation(entity));
        }

        [Test]
        public void ShouldReturnEntityStoredData()
        {
            string previousData = "<repositoryInformation><repositoryMetadata name=\"Person\"><operation operationName=\"DeletePerson\" hasInputParameters=\"True\" procedure=\"DeletePerson\" operationType=\"DeleteOne\" /></repositoryMetadata></repositoryInformation>";

            XmlDocument document = new XmlDocument();
            document.LoadXml(previousData);

            EntitySerializerHelper serializer = new EntitySerializerHelper(document);

            Entity entity = new Entity();
            entity.Name = "Person";
            XmlNode node = serializer.GetEntityStoredData(entity);

            Assert.IsNotNull(node);
            Assert.AreEqual(node.Attributes["name"].Value, "Person");
            Assert.AreEqual(1, node.ChildNodes.Count);
        }
    }
}
